package com.securityMod.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.ForwardLogoutSuccessHandler;

import javax.annotation.Resource;

/**
 * @Author：kangsen
 * @Date：2022/10/25/0025 20:42
 * @Versiion：1.0
 * @Desc:
 */
@Configuration
//开启webSecurity的功能
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /*@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password(passwordEncoder().encode("123456"))
                .roles("ADMIN");
        auth.inMemoryAuthentication()
                .withUser("user")
                .password(passwordEncoder().encode("123"))
                .roles("USER");
    }*/

    @Resource
    private AuthenticationSuccessHandler loginSuccessHandler;
    @Resource
    private AuthenticationFailureHandler loginFailHandler;

    //http请求拦截配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //开启运行iframe页面
        http.headers().frameOptions().disable();
        //配置权限认证
        http.
            //1、配置权限认证
            authorizeRequests()
            .antMatchers("/500").permitAll()
            .antMatchers("/403").permitAll()
            .antMatchers("/404").permitAll()
            .antMatchers("/login").permitAll()
            .anyRequest()//其他任何请求
            .authenticated()//都需要进行身份认证
            .and()
            //2、登陆配置表单认证方式
            .formLogin()
            .loginPage("/login")
            .usernameParameter("username")//登陆表单中用户名的参数名
            .passwordParameter("password")//登陆表单中密码的参数名
            //告诉spring security 在发送制定路径时处理提交的凭证，默认情况下 将用户重定向回用户来自的页面，
            // 登陆表单form中的action的地址，也就是处理认证请求的地址  只要保持表单中的action和httpSecurity里配置的
            // loginProcessingUrl一致就可以了，也不用自己处理 它不会将请求传递给Spring mvc和您的控制器，
            // 所以我们就不需要自己再写一个user/login的请求接口了
            .loginProcessingUrl("/user/login")//配置默认登陆入口
            .defaultSuccessUrl("/index")//登陆成功的默认跳转页面
            .failureUrl("/login?error=true")//登陆失败的跳转页面
            .successHandler(loginSuccessHandler)//登陆成功的处理器
            .failureHandler(loginFailHandler)//登陆失败的处理器
            .and()
            //3、注销
            .logout()
            .logoutUrl("/logout")
            .logoutSuccessHandler(new ForwardLogoutSuccessHandler("/login?error=true"))
            .permitAll()
            .and()
            //4、session管理
            .sessionManagement()
            .invalidSessionUrl("/login")//失效后跳转到登陆页面
            //单用户登陆， 如果一个用户登陆，同一个用户在其他地方登陆将前一个剔除下线
            //.maximumSessions(1).expiredSessionStrategy(expiredSessionStrategy())
            //单用户登陆 如果一个用户登陆，同一个用户在其他地方不能登陆
            //.maximumSessions(1).maxSessionsPreventsLogin(true)
            .and()
            //5、禁用跨站csrf攻击防御
            .csrf()
            .disable();
    }


    @Override
    public void configure(WebSecurity web) throws Exception {
        //配置静态文件不拦截
        web.ignoring().antMatchers("/static/**");
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        // 使用BCrypt加密密码
        return new BCryptPasswordEncoder();
    }

    /*@Bean
    public SessionInformationExpiredStrategy sessionInformationExpiredStrategy(){
        return new SimpleRedirectSessionInformationExpiredStrategy();
    }*/
}
